package com.jplus.mvc.util;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Date;

import com.jplus.core.utill.JUtil;
import com.jplus.mvc.util.AESUtil;
import com.jplus.mvc.util.CRC16;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * DoolockCMD
 */
public class DoolockCMD {

	public static Logger log = LoggerFactory.getLogger(DoolockCMD.class);

	public static enum CMDENUM {
		X12("12", "门锁重置");

		String hexCode;
		String remark;

		private CMDENUM(String hexCode, String remark) {
			this.hexCode = hexCode;
			this.remark = remark;
		}
	}

	@Target({ ElementType.FIELD })
	@Retention(RetentionPolicy.RUNTIME)
	@Documented
	public @interface Sort {
		int value();
	}

	public static class EnCommand {
		/** 指令号 */
		public @Sort(1) byte instructNo;
		/** 指令ID */
		public @Sort(2) int instructId;
		/** 指令有效截止时间 */
		public @Sort(3) int instructExpiredTime;
		/** 数据域明文crc */
		public @Sort(100) byte[] crc;

		protected EnCommand(CMDENUM cmd) {
			this.instructNo = JUtil.hex2Byte(cmd.hexCode);
			this.instructId = (int) (new Date().getTime() / 1000);
			this.instructExpiredTime = instructId + 3600;
		}

		public String build() {
			StringBuilder sb = new StringBuilder();
			try {
				Field[] fs = this.getClass().getFields();
				// ==排序============
				Arrays.sort(fs, (o1, o2) -> {
					Sort s1 = o1.getAnnotation(Sort.class);
					Sort s2 = o2.getAnnotation(Sort.class);
					return s2 == null || s1 == null ? -1 : (s1.value() - s2.value());
				});
				// ==拼装============
				for (Field f : fs) {
					if (f.getAnnotation(Sort.class) == null)
						continue;
					f.setAccessible(true);
					if ("crc".equalsIgnoreCase(f.getName()))
						f.set(this, CRC16.buildCRC16(JUtil.hex2Bytes(sb.toString()), sb.length() / 2));
					if (f.getType() == byte.class)
						sb.append(JUtil.byte2Hex(LittleEndian.get(f.getByte(this))));// 1
					else if (f.getType() == short.class)
						sb.append(JUtil.byte2Hex(LittleEndian.get(f.getShort(this))));// 2
					else if (f.getType() == int.class)
						sb.append(JUtil.byte2Hex(LittleEndian.get(f.getInt(this))));// 4
					else if (f.getType() == long.class)
						sb.append(JUtil.byte2Hex(LittleEndian.get(f.getLong(this))));// 8
					if (f.getType() == byte[].class) {
						byte[] bs = (byte[]) f.get(this);
						for (byte b : bs)
							sb.append(JUtil.byte2Hex(LittleEndian.get(b)));
					}
					log.info(sb.toString());
				}
			} catch (Exception e) {
				log.error("CMD ERROR:", e);
			}
			return sb.toString();
		}
	}

	/** 门锁重置 */
	public static class ResetCommand extends EnCommand {
		public ResetCommand() {
			super(CMDENUM.X12);
		}
	}

	public static void main(String[] args) {
		String key = "1234567890123456";
		// String key = "0SNxqB0VaPVAyn85";
		String cmdHexPub = new ResetCommand().build();
		String cmdHexPri = JUtil.byte2Hex(AESUtil.encrypt(JUtil.hex2Bytes(cmdHexPub), key.getBytes()));
		log.info("密钥：" + key + "\t密文：" + cmdHexPri);

		log.info(JUtil.byte2Hex(AESUtil.decrypt(JUtil.hex2Bytes("707ccd0cdcbd904bbc35b1437e"), key.getBytes())));
	}
}